package yxy.game.pm2.module.fortdefeat;

import java.util.*;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.TypeReference;
import org.redisson.api.RMap;
import yxy.cherry.battle.module.Position;
import yxy.cherry.battle.module.record.FighterPosition;
import yxy.cherry.battle.module.record.FighterSide;
import yxy.cherry.battle.module.record.result.StatisticFighter;
import yxy.cherry.data.DataCenter;
import yxy.cherry.data.bean.running;
import yxy.cherry.data.bean.runningbox;
import yxy.cherry.data.bean.runningdate;
import yxy.cherry.data.script.fomula;
import yxy.cherry.game.base.redis.RedisManager;
import yxy.cherry.game.base.redis.RedisType;
import yxy.game.pm2.Result;
import yxy.game.pm2.bean.Currency;
import yxy.game.pm2.bean.Format;
import yxy.game.pm2.bean.PlayerBean;
import yxy.game.pm2.bean.mq.CCReason;
import yxy.game.pm2.bean.task.TaskType;
import yxy.game.pm2.message.BattleMessage;
import yxy.game.pm2.message.BattleMessage.BattleExecuteResponse;
import yxy.game.pm2.message.FormatMessage;
import yxy.game.pm2.message.FortDefeatMessage;
import yxy.game.pm2.module.CurrencyHandle;
import yxy.game.pm2.module.battle.*;
import yxy.game.pm2.module.battle.FighterModule.InitHpLossRatio;
import yxy.game.pm2.module.hero.FormatHandle;
import yxy.game.pm2.module.task.TaskHandle;

public class FortDefeatHandle extends BattleModuleHandle {

    final public static int battleExpireDay = 1;// 战斗数据过期时间（天）

    protected String code() {
        return BattleType.FORTDEFEAT.name();
    }

    public BattleMessage.BattleResponse battleResponse(String playerCode, int mapId) throws Exception {
        BattleHandle battleHandle = new BattleHandle();
        BattleModule battleModule = createBattleModule(playerCode, mapId);
        return battleHandle.battleResponse(battleModule);
    }

    public BattleExecuteResponse battleResponseExecute(String playerCode, BattleMessage.BattleExecuteRequest request) throws Exception {
        BattleModule battleModule = BattleModule.get(playerCode, code());
        FortDefeatModule fortDefeatModule = FortDefeatModule.get(playerCode);
        try {
            if (fortDefeatModule.tryLock()) {
                int[] angersTeamA = null;
                if (request != null) {
                    List<BattleMessage.FighterInfo> fighterInfos = request.getFormatList();
                    ArrayList<BattleMessage.FighterInfo> fighterInfosTeamA = new ArrayList<>();
                    for (BattleMessage.FighterInfo fighterInfo : fighterInfos) {
                        FighterPosition fp = FighterPosition.forNumber(fighterInfo.getPosition().getNumber());
                        if (fp.getSide().equals(FighterSide.LEFT)) {
                            fighterInfosTeamA.add(fighterInfo);
                        }
                    }
                    angersTeamA = new BattleHandle().angersFromFormatList(fighterInfosTeamA);
                }
                fortDefeatModule.setAngers(angersTeamA);
                fortDefeatModule.set();
            }
        } catch (Exception e) {
        } finally {
            fortDefeatModule.unlock();
        }
        BattleExecuteResponse res = new BattleHandle().battleResponseExecute(battleModule, fortDefeatModule.getAngers(), null);

        saveHp(playerCode, fortDefeatModule, battleModule);

        return res;
    }

    public BattleExecuteResponse battleResponseExecuteQuick(String playerCode, int mapId) {
        BattleModule battleModule = createBattleModule(playerCode, mapId);
        FortDefeatModule fortDefeatModule = FortDefeatModule.get(playerCode);

        BattleExecuteResponse res = new BattleHandle().battleResponseExecute(battleModule, fortDefeatModule.getAngers(), null);

        saveHp(playerCode, fortDefeatModule, battleModule);

        return res;
    }

    private void saveHp(String playerCode, FortDefeatModule fortDefeatModule, BattleModule battleModule) {
        try {
            if (fortDefeatModule.tryLock()) {
                Map<Position, String> heroCodes = new FormatHandle().formatCodes(playerCode, fortDefeatModule.getFormat());
                for (StatisticFighter fighter : battleModule.getStatistics()) {
                    if (!fighter.getPos().getSide().equals(FighterSide.LEFT)) {
                        continue;
                    }
                    Position position = fighter.getPos().getPosition();
                    if (position == null) {
                        continue;
                    }
                    int ratio = (int) (fighter.getHpc() * 10000 / fighter.getHpu());
                    String heroCode = heroCodes.get(fighter.getPos().getPosition());
                    if (heroCode != null && ratio < 10000) {
                        fortDefeatModule.getHeroHp().put(heroCode, ratio);
                    }
                }
                fortDefeatModule.set();
            }
        } catch (Exception e) {
        } finally {
            fortDefeatModule.unlock();
        }
    }

    private BattleModule createBattleModule(String playerCode, int mapId) {
        FortDefeatModule fortDefeatModule = FortDefeatModule.get(playerCode);
        BattleHandle battleHandle = new BattleHandle();

        BattleModule battleModule = BattleModule.create(playerCode);
        battleModule.setType(BattleType.FORTDEFEAT);
        battleModule.setCode(code());

        // 玩家的team
        TeamModule teamA = battleHandle.teamPlayer(playerCode, fortDefeatModule.getFormat());
        Map<Position, String> heroCodes = new FormatHandle().formatCodes(playerCode, fortDefeatModule.getFormat());
        for (Position position : Position.values()) {
            FighterModule fighterModule = teamA.fighter(position);
            String code = heroCodes.get(position);
            if (code == null || fighterModule == null) {
                continue;
            }
            if (!fortDefeatModule.getHeroHp().containsKey(code)) {
                continue;
            }
            int ratio = fortDefeatModule.getHeroHp().get(code);
            fighterModule.setInitHp(new InitHpLossRatio(ratio));
        }
        battleModule.setTeamA(teamA);

        // 征战地图
        TeamModule teamB = teamFortDefeat(mapId, playerCode);
        battleModule.setTeamB(teamB);

        battleModule.setSettlement(SettlementFortDefeat.create(playerCode, mapId));

//		PlayerBean playerBean = PlayerBean.get(playerCode);
//		int skipLevel = fomula.速战功能等级条件.intValue();
//		int skipVip = fomula.速战功能VIP条件.intValue();
//		battleModule.setSkip(playerBean.getViplevel() >= skipVip || playerBean.getLevel() >= skipLevel);

        battleModule.set(battleExpireDay);
        return battleModule;
    }

    public TeamModule teamFortDefeat(int mapid, String playerCode) {
        TeamModule team = new TeamModule();
        running mapdata = DataCenter.getData(mapid, running.class);


        RMap<String, ArrayList<FighterModule>> rMap = RedisManager.getInstance().getConnection(RedisType.REDIS_DATA).client().getMap("INIT:running");
        JSONArray arrary = (JSONArray) JSONArray.toJSON(rMap.get(String.valueOf(mapid)));
        ArrayList<FighterModule> fighterModules = JSON.parseObject(arrary.toString(), new TypeReference<ArrayList<FighterModule>>() {
        });

        //todo 动态改变怪物战力
        ForDefeatDynamicModule module = ForDefeatDynamicModule.get(playerCode);
        int degree = module.getDegree();//难度等级（动态）

        // 武将
        for (int i = 0; i < mapdata.getHeroid().length; i++) {
            Position position = Position.forValue(i + 1);
            int heroid = mapdata.getHeroid()[i];
            if (heroid == -1) continue;
            FighterModule fighterModule = fighterModules.get(i);
            //根据等级提升怪物难度
            fighterModule.setLevel(fighterModule.getLevel() + degree * 5);
            fighterModule.getProperty().addPropertyDataBasicDegree(degree, 10);

            team.addfighter(position, fighterModule);
        }
        // 神器
        WeaponModule weapon = WeaponModule.create(mapdata.getWeapondataid(), mapdata.getWeaponlv(), 0, 0, mapdata.getWeaponskilllv());
        team.setWeapon(weapon);

        // 信息
        team.setName(mapdata.getName());
        team.setHead(mapdata.getHeadid());
        team.setPower(mapdata.getDps());

        return team;
    }

    /**
     * 处理下一个关卡
     *
     * @param playerCode
     * @param mapId
     * @param rewards
     */
    public void nextMap(String playerCode, int mapId, Collection<Currency> rewards) {
        FortDefeatModule fortDefeatModule = FortDefeatModule.get(playerCode);
        try {
            if (fortDefeatModule.tryLock()) {
                fortDefeatModule.setMapId(mapId);
                running mapdata = DataCenter.getData(mapId, running.class);
                int nextId = mapId + 1;

                running nextdata = DataCenter.getData(nextId, running.class);
                if (nextdata == null || nextdata.getDifficulty() != fortDefeatModule.getType().getNumber()) {
                    // 最后一关，说明完成了
                    fortDefeatModule.finish();

                    //如果是困难难度，怪物难度百分比+10
                    addDynamic(fortDefeatModule.getType().getNumber(), playerCode);

                }
                fortDefeatModule.hasrewards(rewards);
                fortDefeatModule.set();
                TaskHandle.handle(playerCode, TaskType.统计型_副本_过关斩将_胜利_次数, 1);
                TaskHandle.handle(playerCode, TaskType.指标型_副本_过关斩将_关卡_达到, mapdata.getLevel());
            }
        } catch (Exception e) {
        } finally {
            fortDefeatModule.unlock();
        }
    }

    /**
     * 困难模式就增加难度
     *
     * @param number
     * @param playerCode
     */
    private void addDynamic(int number, String playerCode) {
        if (number < 3) return;
        ForDefeatDynamicModule module = ForDefeatDynamicModule.get(playerCode);
        module.setDegree(module.getDegree() + 1);
        module.set();
    }

    /**
     * 征战奖励
     */
    static public Collection<Currency> mapReward(int mapId) {
        ArrayList<Currency> rewards = new ArrayList<>();
        // 固定奖励
        running _mapdata = DataCenter.getData(mapId, running.class);
        if (_mapdata != null) {
            rewards.addAll(Currency.create(_mapdata.getRewardtype(), _mapdata.getRewardid(), _mapdata.getRewardnum()));
        }
        return rewards;
    }

    /**
     * 扫荡挂机随机奖励
     */
    static public Collection<Currency> sweepReward(int mapId, int sweepId) {
        ArrayList<Currency> rewards = new ArrayList<>();
        for (int mid = mapId; mid <= sweepId; mid++) {
            running _mapdata = DataCenter.getData(mid, running.class);
            if (_mapdata != null) {
                rewards.addAll(Currency.create(_mapdata.getRewardtype(), _mapdata.getRewardid(), _mapdata.getRewardnum()));
            }
            // 顺便把宝箱也领了
            runningbox _runningbox = DataCenter.getData(mid, runningbox.class);
            if (_runningbox != null) {
                rewards.addAll(Currency.create(_runningbox.getRewardtype(), _runningbox.getRewardid(), _runningbox.getRewardnum()));
            }
        }
        return Currency.merge(rewards);
    }

    public Result boxReward(String playerCode, int boxId, FortDefeatMessage.FortDefeatBoxResponse.Builder response) {
        FortDefeatModule fortDefeatModule = FortDefeatModule.get(playerCode);
        try {
            if (fortDefeatModule.tryLock()) {
                runningbox _data = DataCenter.getData(boxId, runningbox.class);
                for (Integer getId : fortDefeatModule.getBox()) {
                    if (_data.getId() == getId) {
                        return Result.FortDefeatBoxRewarded;// 宝箱已经领过
                    }
                }
                if (fortDefeatModule.getType() == null || _data == null || fortDefeatModule.getType().getNumber() != _data.getDifficulty()) {
                    return Result.FortDefeatBoxCantReward;// 宝箱不能领取
                }
                if (fortDefeatModule.getMapId() < _data.getId()) {
                    return Result.FortDefeatBoxCantReward;// 宝箱不能领取
                }

                Collection<Currency> rewards = Currency.create(_data.getRewardtype(), _data.getRewardid(), _data.getRewardnum());
                new CurrencyHandle().addCurrency(playerCode, CCReason.过关斩将, rewards);
                response.addAllRewards(new CurrencyHandle().packItems(rewards));
                response.setBox(_data.getId());

                fortDefeatModule.getBox().add(_data.getId());
                fortDefeatModule.set();

                return Result.Success;
            }
        } catch (Exception e) {
        } finally {
            fortDefeatModule.unlock();
        }
        return Result.DataError;
    }

    public Result sweep(String playerCode, FortDefeatMessage.FortDefeatSweepResponse.Builder response) {
        FortDefeatModule fortDefeatModule = FortDefeatModule.get(playerCode);
        try {
            if (fortDefeatModule.tryLock()) {
                if (fortDefeatModule.getType() == null) {
                    return Result.ParamError;
                }

                int sweepId = fortDefeatModule.getSweepId();
                int mapId = fortDefeatModule.getMapId();

                if (sweepId <= 0 || sweepId <= mapId) {
                    // 没有扫荡
                    return Result.FortDefeatNoStageCanSweep;// 没有可以扫荡的关卡
                }
                // 检查sweepId
                running _running = DataCenter.getData(sweepId, running.class);
                if (fortDefeatModule.getType().getNumber() != _running.getDifficulty()) {
                    return Result.ParamError;
                }

                if (mapId == 0) {
                    mapId = fortDefeatModule.getType().getStartId();
                }

                Collection<Currency> rewards = sweepReward(mapId, sweepId);
                new CurrencyHandle().addCurrency(playerCode, CCReason.过关斩将, rewards);

                fortDefeatModule.setMapId(sweepId);
                fortDefeatModule.set();

                response.addAllRewards(new CurrencyHandle().packItems(Currency.merge(rewards)));

                return Result.Success;
            }
        } catch (Exception e) {
        } finally {
            fortDefeatModule.unlock();
        }
        return Result.DataError;
    }

    public Result checkFormat(String playerCode, FormatMessage.Format formatrequest) {
        String fu = formatrequest.getFU() == "" ? null : formatrequest.getFU();
        String fm = formatrequest.getFM() == "" ? null : formatrequest.getFM();
        String fd = formatrequest.getFD() == "" ? null : formatrequest.getFD();
        String bu = formatrequest.getBU() == "" ? null : formatrequest.getBU();
        String bm = formatrequest.getBM() == "" ? null : formatrequest.getBM();
        String bd = formatrequest.getBD() == "" ? null : formatrequest.getBD();
        int nb = formatrequest.getNB();

        FortDefeatModule fortDefeatModule = FortDefeatModule.get(playerCode);
        try {
            if (fortDefeatModule.tryLock()) {
                FormatHandle formatModule = new FormatHandle();
                Format format = fortDefeatModule.getFormat();
                format.setFu(fu);
                format.setFm(fm);
                format.setFd(fd);
                format.setBu(bu);
                format.setBm(bm);
                format.setBd(bd);
                format.setNb(nb);

                Result result = formatModule.check(playerCode, format, new ArrayList<>());
                if (!result.equals(Result.Success)) {
                    return result;
                }
                // TODO 有没有没血的武将

                fortDefeatModule.set();

                return Result.Success;
            }
        } catch (Exception e) {
        } finally {
            fortDefeatModule.unlock();
        }
        return Result.DataError;
    }

    public Result checkFormatCanBattle(String playerCode) {
        BattleHandle battleHandle = new BattleHandle();
        FortDefeatModule fortDefeatModule = FortDefeatModule.get(playerCode);
        TeamModule teamA = battleHandle.teamPlayer(playerCode, fortDefeatModule.getFormat());
        Map<Position, String> heroCodes = new FormatHandle().formatCodes(playerCode, fortDefeatModule.getFormat());
        int liveHerosCount = 0;
        for (Position position : Position.values()) {
            FighterModule fighterModule = teamA.fighter(position);
            String code = heroCodes.get(position);
            if (code == null || fighterModule == null) {
                continue;
            }
            if (!fortDefeatModule.getHeroHp().containsKey(code)) {
                liveHerosCount++;
                continue;
            }
            int ratio = fortDefeatModule.getHeroHp().get(code);
            fighterModule.setInitHp(new InitHpLossRatio(ratio));
            if (ratio > 0) {
                liveHerosCount++;
            }
        }
        if (liveHerosCount <= 0) {
            return Result.ParamError;// TODO 没有活着的武将了
        }
        return Result.Success;
    }

    public runningdate typeData(FortDefeatType type) {
        Collection<runningdate> datas = DataCenter.getAllData(runningdate.class).values();
        for (runningdate data : datas) {
            if (data.getType() == type.getNumber()) {
                return data;
            }
        }
        return null;
    }

}
